package test.test01.network.rollback_TCP;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EchoServer {
    private ServerSocket serverSocket;

    public EchoServer(int port) throws IOException{
        serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException{
        System.out.println("服务器启动中...");
        ExecutorService threadPool = Executors.newCachedThreadPool();//创建线程池，用于处理客户端连接，提高效率 
        while(true){
            //建立连接，建立连接的过程中，会阻塞等待
            Socket socket = serverSocket.accept();
            // //多线程版本
            // //多线程解决外层循环阻塞问题
            // Thread t = new Thread(()->{
            //     //lambda表达式捕获到this和socket，this是EchoServer对象，socket是accept方法返回的Socket对象
            //     this.processConnection(socket);
            // });
            // t.start();

            //线程池版本
            threadPool.submit(()->{
                this.processConnection(socket);
            });
        }
        
    }
    private void processConnection(Socket socket){
        System.out.printf("[%s:%d] 客户端建立连接\n",socket.getInetAddress().toString(),socket.getPort());
        try(InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream()){
                //实现通信代码
                //一个客户端可能会有多个请求，因此需要循环读取
                Scanner sc = new Scanner(inputStream);    
                PrintWriter pw = new PrintWriter(outputStream);   
                while(true){
                    //1.读取请求并解析
                    if(!sc.hasNext()){
                        //如果sc中没有数据了，就说明客户端已经断开连接了
                        System.out.printf("[%s:%d] 客户端断开连接\n",socket.getInetAddress().toString(),socket.getPort());
                        break;
                    }
                    String request = sc.next();
                    //2.根据请求计算响应
                    String response = process(request);
                    //3.把响应写回客户端
                    pw.println(response);
                    //刷新缓冲区，把数据读入网卡
                    pw.flush();
                    //4.打印日志
                    System.out.printf("[%s:%d] req: %s,resp: %s\n",socket.getInetAddress().toString(),socket.getPort(),request,response);
                }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                socket.close();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException{
        EchoServer server = new EchoServer(9090);
        server.start();
    }
}
